package com.bbva.gptf.back.servicio.orden;

import java.math.BigDecimal;
import java.math.MathContext;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;

import com.bbva.gptf.back.util.OrdenaDetalleOrdenPorClasificacion;
import com.bbva.gptf.back.util.OrdenaDetalleOrdenPorContrato;
import com.bbva.gptf.back.util.OrdenaOrdenPorFolio;
import com.bbva.gptf.back.util.OrdenaOrdenTpContrato;
import com.bbva.gptf.dto.bean.BoletaOperDeuda;
import com.bbva.gptf.dto.bean.BoletaOperEquity;
import com.bbva.gptf.dto.bean.BoletaPostReparto;
import com.bbva.gptf.dto.bean.DetalleOrden;
import com.bbva.gptf.dto.bean.Liquidacion;
import com.bbva.gptf.dto.bean.Orden;
import com.bbva.gptf.dto.bean.ReporteAsignacion;
import com.bbva.gptf.dto.bean.Usuario;
import com.bbva.gptf.dto.servicio.carga.ServicioParametro;
import com.bbva.gptf.dto.servicio.orden.ServicioOrdenFacade;
import com.bbva.gptf.dto.servicio.reporteo.ServicioOrden;
import com.bbva.gptf.dto.servicio.usuario.ServicioUsuario;
import com.bbva.gptf.dto.util.Utilidades;
import com.bbva.jee.arq.spring.core.httpService.HttpService;

@HttpService(serviceName = "servicioOrdenFacadeHttp")
public class ServicioOrdenFacadeImpl implements ServicioOrdenFacade {

	@Autowired
	private ServicioOrden servicioOrden;
	@Autowired
	private ServicioParametro servicioParametro;
	@Autowired
	private ServicioUsuario servicioUsuario;

	private static final NumberFormat FORMATOENTERO = new DecimalFormat(
			"###,###,###,###,##0");

	private static final NumberFormat FORMATODECIMAL = new DecimalFormat(
			"###,###,###,###,##0.00");

	@Override
	public boolean actualizarOrden(final Usuario usuario, final Orden orden) {
		try {
			boolean res = false;
			if (usuario == null || orden == null) {
				return false;
			}
			if (usuario.getPerfil().getMercado().getCdMercado().intValue() == 1) {
				/* Actualizamos orden para mercado de deuda */
				if (orden.getStOrden().intValue() == 2) {
					res = validarReparto(orden) ? res = servicioOrden.actualizarOrdenDeuda(orden) : false;
				} else {
					res = servicioOrden.actualizarOrdenDeuda(orden);
				}
			} else {
				/* Actualizamos orden para mercado de capital */
				res = servicioOrden.actualizarOrdenCapital(orden);
			}
			return res;
		} catch (final Exception ex) {
			return false;
		}
	}

	@Override
	public boolean eliminarOrden(final Usuario usuario, final Orden orden) {
		try {
			boolean res = false;
			if (usuario == null || orden == null) {
				return false;
			}
			res = servicioOrden.eliminarOrden(orden.getCdOrden());
			return res;
		} catch (final Exception ex) {
			return false;
		}
	}
	
	private String aEntero(final BigDecimal valor) {
		try {
			return FORMATOENTERO.format(valor.intValue());
		} catch (final IllegalArgumentException e) {
			return "";
		}
	}

	private String aNumero(final BigDecimal valor) {
		try {
			return FORMATODECIMAL.format(valor.doubleValue());
		} catch (final IllegalArgumentException e) {
			return "";
		}
	}

	public String incialesGestor(final BigDecimal cd) {
		final String nombre = servicioUsuario.obtenerUsuario(cd).getNbUsuario();
		String iniciales = "";
		final String[] texto = nombre.split(" ");
		for (final String name : texto) {
			final char inicial = name.charAt(0);
			iniciales = iniciales + inicial;
		}
		return iniciales;
	}

	@Override
	public List<Orden> obtenerAllOrdenesAsignacion() {
		final List<BigDecimal> listaStOrden = new ArrayList<BigDecimal>();
		listaStOrden.add(new BigDecimal(2));
		listaStOrden.add(new BigDecimal(3));
		listaStOrden.add(new BigDecimal(4));
		return servicioOrden.obtenerALLOrdenDeuda(listaStOrden);
	}

	@Override
	public List<ReporteAsignacion> obtenerBoletaAsignacion(final Orden orden) {
		// TODO Auto-generated method stub
		final List<ReporteAsignacion> boletaAsig = new ArrayList<ReporteAsignacion>();
		final ReporteAsignacion asigFolio = new ReporteAsignacion();
		final ReporteAsignacion asigInstr = new ReporteAsignacion();

		asigFolio.setGrupoContrato("Folio " + orden.getNuFolio());
		asigFolio.setNivel("1");
		asigInstr.setGrupoContrato(orden.getInstrumento());
		asigInstr.setNivel("1");
		boletaAsig.add(asigFolio);
		boletaAsig.add(asigInstr);
		for (final DetalleOrden detalle : orden.getDetallesOrden()) {
			String stDetalle = "";
			final ReporteAsignacion asigDetalle = new ReporteAsignacion();
			asigDetalle.setGrupoContrato(detalle.getCdContrato().toString());
			asigDetalle.setTipo(detalle.getTpContrato());
			asigDetalle.setTitulos(detalle.getCtTituloPost().toString());
			asigDetalle.setOperacion(obtenerOperacion(orden.getTpOperacion()));
			asigDetalle.setPrecio(detalle.getImPrecioAsig() != null ? detalle.getImPrecioAsig().toPlainString() : null);
			asigDetalle.setTasa(detalle.getPcTasaAsig() != null  ? ( StringUtils.isBlank(detalle.getPcTasaAsig().toPlainString()) ? null : detalle.getPcTasaAsig().divide(new BigDecimal(100)).toPlainString()) : null);
			asigDetalle.setPlazo(detalle.getDuPlazoAsig()!= null ? detalle.getDuPlazoAsig().toPlainString():null);
			asigDetalle.setMonto(detalle.getToImporteAsig() != null ? detalle.getToImporteAsig().toPlainString() : null);
			asigDetalle
					.setCveLiquidacion(valida(detalle.getCdCveLiquidacion()));
			if (detalle.getStDetalle().equals(new BigDecimal(0))) {
				stDetalle = "No Enviado";
			}
			if (detalle.getStDetalle().equals(new BigDecimal(1))) {
				stDetalle = "Enviado a SIVA/MUV, HG: "
						+ valida(detalle.getNuFolioHg());
			}
			if (detalle.getStDetalle().equals(new BigDecimal(2))) {
				stDetalle = "Exito, BUC: " + valida(detalle.getNuFolioBuc());
			}
			if (detalle.getStDetalle().equals(new BigDecimal(3))) {
				stDetalle = "Error: " + valida(detalle.getNbMsjError());
			}
			asigDetalle.setEstado(stDetalle);
			asigDetalle.setGestor(valida(orden.getInicialesGestor()));
			asigDetalle.setNivel("2");
			boletaAsig.add(asigDetalle);
		}
		return boletaAsig;
	}

	@Override
	public List<BoletaOperDeuda> obtenerBoletaDeu(final Orden orden) {
		// TODO Auto-generated method stub
		final List<BoletaOperDeuda> boletaDeu = new ArrayList<BoletaOperDeuda>();
		final List<String> portafolio = obtenerPortafolios(orden
				.getDetallesOrden());
		if (!portafolio.isEmpty()) {
			final BoletaOperDeuda folio = new BoletaOperDeuda();
			folio.setNuFolio("Folio " + orden.getNuFolio());
			folio.setNivel("0");
			boletaDeu.add(folio);
			for (final String porta : portafolio) {
				final BoletaOperDeuda boleta = new BoletaOperDeuda();
				BigDecimal cantSolicitada = new BigDecimal(0);
				BigDecimal titulos = new BigDecimal(0);
				String nomReaTit;
				String impNomReaTit;
				for (final DetalleOrden detalle : orden.getDetallesOrden()) {
					if (detalle.getTpContrato().equals(porta)) {
						cantSolicitada = cantSolicitada.add(detalle
								.getImMonto());
						titulos = titulos.add(detalle.getCtTitulo());
					}
				}
				nomReaTit = "REAL";
				impNomReaTit = cantSolicitada.toPlainString();
				if (orden.getStTituloBoleta() == 1) {
					nomReaTit = "TIT";
					impNomReaTit = cantSolicitada.toPlainString();
				} else {
					if (orden.getStNominal() != null) {
						if (orden.getStNominal().equals(new BigDecimal(1))) {
							nomReaTit = "NOM";
							impNomReaTit = orden.getImValorNom()
									.intValue() > 0 ? (orden.getImValorNom()
									.multiply(titulos)).toPlainString() : (BigDecimal.ZERO).toPlainString();
						}
					}
				}
				boleta.setGestor(valida(incialesGestor(orden.getCdGestor())));
				boleta.setFhSolicitud(DateFormatUtils.format(
						orden.getFhOperacion(), "dd/MM/yyyy").toString());
				boleta.setFhLiquidacion(valida(orden
						.getFechaLiquidacionBoleta()));
				boleta.setOperacion(valida(obtenerOperacion(orden
						.getTpOperacion())));
				boleta.setTv(valida(orden.getCdValorBmv()));
				boleta.setEmisora(valida(orden.getCdEmisora()));
				boleta.setSerie(valida(orden.getCdSerie()));
				boleta.setDxv(valida(orden.getDiasPorVencerBoleta()));
				boleta.setCantSolicitada(impNomReaTit);
				boleta.setTitulos(titulos.toPlainString());
				boleta.setPrecio(orden.getPrecioBoleta() != null ? orden.getPrecioBoleta().toPlainString() : null);
				boleta.setTasa(orden.getTasaBoleta() != null ? orden
						.getTasaBoleta().toPlainString() : null);
				boleta.setPortafolio(valida(porta));
				boleta.setNomReaTit(valida(nomReaTit));
				boleta.setComentario(valida(orden.getTxJustificacion()));
				boleta.setNivel("1");
				boletaDeu.add(boleta);
			}
			final BoletaOperDeuda boleta = new BoletaOperDeuda();
			/*
			 * BigDecimal totalCantSolicitada = new BigDecimal(0); for (final
			 * DetalleOrden detalle : orden.getDetallesOrden()) {
			 * totalCantSolicitada = totalCantSolicitada.add(detalle
			 * .getImMonto()); }
			 */
			String totNomReaTit = orden.getToImporte().toPlainString();
			if (orden.getStTituloBoleta() == 1) {
				totNomReaTit = orden.getCtTitulo().toPlainString();
			} else {
				if (orden.getStNominal() != null) {
					if (orden.getStNominal().equals(new BigDecimal(1))) {
						totNomReaTit = orden.getToImporteNominal().toPlainString();
					}
				}
			}
			boleta.setTotalCantSolicitada(totNomReaTit);
			boleta.setNivel("2");
			boletaDeu.add(boleta);
		}
		return boletaDeu;
	}

	@Override
	public List<BoletaOperEquity> obtenerBoletaEquity(final Orden orden) {
		// TODO Auto-generated method stub
		final List<BoletaOperEquity> boletaEquity = new ArrayList<BoletaOperEquity>();
		final List<DetalleOrden> detalles = orden.getDetallesOrden();
		boletaEquity.addAll(obtenerCabeceraBoleta(orden));
		Collections.sort(detalles, new OrdenaOrdenTpContrato());
		for (final DetalleOrden detOrden : detalles) {
			final BoletaOperEquity boleta = new BoletaOperEquity();
			boleta.setFolioGpt(valida(orden.getNuFolio()));
			boleta.setRec(Utilidades.aFechaFormato(orden.getTmUmo(),
					"dd/MM/yyyy HH:mm:ss"));
			boleta.setOper(valida(obtenerOperacion(orden.getTpOperacion())));
			boleta.setCliente(valida(detOrden.getTpContrato()));
			boleta.setContrato(valida(detOrden.getCdContrato()));
			boleta.setTitulos(detOrden.getCtTitulo().toPlainString());
			boleta.setEmisora(valida(orden.getCdEmisora()));
			boleta.setSerie(valida(orden.getCdSerie()));
			boleta.setPrecio(orden.getPrecioBoleta() != null ? "$"
					+ aNumero(orden.getPrecioBoleta()) : "MKT");
			boleta.setComentario(valida(orden.getTxJustificacion()));
			boletaEquity.add(boleta);

		}
		return boletaEquity;
	}

	public List<BoletaOperEquity> obtenerCabeceraBoleta(final Orden orden) {
		final List<BoletaOperEquity> cabecera = new ArrayList<BoletaOperEquity>();
		final BoletaOperEquity boletaGlobal = new BoletaOperEquity();
		final BoletaOperEquity boletaEnca = new BoletaOperEquity();
		boletaGlobal.setFolioGpt(valida(orden.getNuFolio()));
		boletaGlobal.setRec(Utilidades.aFechaFormato(orden.getTmUmo(),
				"dd/MM/yyyy HH:mm:ss"));
		boletaGlobal.setOper(valida(obtenerOperacion(orden.getTpOperacion())));
		boletaGlobal.setCliente("-");
		boletaGlobal.setContrato("GLOBAL");
		boletaGlobal.setTitulos(orden.getCtTitulo().toPlainString());
		boletaGlobal.setEmisora(valida(orden.getCdEmisora()));
		boletaGlobal.setSerie(valida(orden.getCdSerie()));
		boletaGlobal.setPrecio(orden.getPrecioBoleta() != null ? "$"
				+ aNumero(orden.getPrecioBoleta()) : "MKT");
		boletaGlobal.setComentario(valida(orden.getTxJustificacion()));
		boletaEnca.setFolioGpt("DISTRIBUCION");
		cabecera.add(boletaGlobal);
		cabecera.add(boletaEnca);
		return cabecera;
	}

	@Override
	public List<Liquidacion> obtenerClavesLiquidacion() {
		final String CVELIQUID = "cveliquid%";
		return servicioParametro.obtenerLiquidacion(CVELIQUID);
	}

	@Override
	public List<Orden> obtenerFolioOrdenes(final Usuario usuario,
			final BigDecimal stOrden) {
		if (usuario == null || stOrden == null) {
			return null;
		}
		List<Orden> ordenes = new ArrayList<Orden>();
		if (usuario.getPerfil().getMercado().getCdMercado().intValue() == 1) {
			/* Obtenemos ordenes para mercado de deuda */
			ordenes = servicioOrden.obtenerFolioOrdenesDeuda(stOrden,
					usuario.getCdUsuario());
		} else {
			/* Obtenemos ordenes para mercado de capital */
			ordenes = servicioOrden.obtenerFolioOrdenesCapital(stOrden,
					usuario.getCdUsuario());
		}
		Collections.sort(ordenes, new OrdenaOrdenPorFolio());
		return ordenes;
	}

	public String obtenerOperacion(final BigDecimal tpOperacion) {
		String tpOper;
		if (tpOperacion.equals(new BigDecimal(1))) {
			tpOper = "C";
			return tpOper;
		} else {
			if (tpOperacion.equals(new BigDecimal(2))) {
				tpOper = "V";
				return tpOper;
			}
		}
		return null;
	}

	@Override
	public Orden obtenerOrden(final Usuario usuario, final BigDecimal cdOrden,
			final BigDecimal stOrden) {
		if (usuario == null || cdOrden == null || stOrden == null) {
			return null;
		}
		Orden orden;
		if (usuario.getPerfil().getMercado().getCdMercado().intValue() == 1) {
			/* Obtenemos ordenes para mercado de deuda */
			orden = servicioOrden.obtenerOrdenDeudaPorCdOrdenDeuda(cdOrden);
		} else {
			/* Obtenemos ordenes para mercado de capital */
			orden = servicioOrden.obtenerOrdenCapitalPorCdOrdenCapital(cdOrden);
		}
//		if (orden != null) {
//			Collections.sort(orden.getDetallesOrden(),
//					new OrdenaDetalleOrdenPorClasificacion());
//		}
		if (!orden.getStOrden().equals(stOrden)) {
			orden = null;
		}
		return orden;
	}

	@Override
	public Orden obtenerOrdenDeuda(final BigDecimal cdOrden) {
		Orden orden;
		orden = servicioOrden.obtenerOrdenDeudaPorCdOrdenDeuda(cdOrden);
		if (orden != null) {
			Collections.sort(orden.getDetallesOrden(),
					new OrdenaDetalleOrdenPorContrato());
		}
		return orden;
	}

	@Override
	public List<Orden> obtenerOrdenes(final Usuario usuario,
			final BigDecimal stOrden) {
		if (usuario == null || stOrden == null) {
			return null;
		}
		List<Orden> ordenes;
		if (usuario.getPerfil().getMercado().getCdMercado().intValue() == 1) {
			/* Obtenemos ordenes para mercado de deuda */
			ordenes = servicioOrden.obtenerOrdenesDeuda(stOrden,
					usuario.getCdUsuario());
		} else {
			/* Obtenemos ordenes para mercado de capital */
			ordenes = servicioOrden.obtenerOrdenesCapital(stOrden,
					usuario.getCdUsuario());
		}
		if (ordenes != null && !ordenes.isEmpty()) {
			for (final Orden orden : ordenes) {
				Collections.sort(orden.getDetallesOrden(),
						new OrdenaDetalleOrdenPorClasificacion());
			}
		}
		return ordenes;
	}

	@Override
	public List<Orden> obtenerOrdenesAsignacion(final BigDecimal stOrden) {
		final List<BigDecimal> listaStOrden = new ArrayList<BigDecimal>();
		listaStOrden.add(stOrden);
		return servicioOrden.obtenerALLOrdenDeuda(listaStOrden);
	}

	public List<String> obtenerPortafolios(final List<DetalleOrden> detalle) {
		if (!detalle.isEmpty()) {
			final HashSet<String> estatusContrato = new HashSet<String>();
			final List<String> portafolio = new ArrayList<String>();
			for (final DetalleOrden det : detalle) {
				if (StringUtils.isBlank(det.getTpContrato())) {
					estatusContrato.add("");
				} else {
					estatusContrato.add(det.getTpContrato());
				}
			}
			portafolio.addAll(estatusContrato);
			return portafolio;
		}
		return null;
	}

	@Override
	public Orden postreparto(final Orden orden) {
		try {
			final BigDecimal precio = orden.getImPrecioPost();
			BigDecimal totalTitulos = orden.getCtTituloPost();
			BigDecimal totalMonto = orden.getToImportePost();
			BigDecimal auxMonto = BigDecimal.ZERO;
			BigDecimal auxTitulos = BigDecimal.ZERO;
			BigDecimal sumaTitulos = BigDecimal.ZERO;
			int indexMax = -1;
			BigDecimal porcentajeMax = BigDecimal.ZERO;
			BigDecimal auxPorcentaje = BigDecimal.ZERO;
			BigDecimal diferencia = BigDecimal.ZERO;
			if (totalTitulos.intValue() > 0) {
				totalMonto = precio.multiply(totalTitulos);
			}
			totalTitulos = totalMonto.divide(precio);
			totalTitulos = totalTitulos.setScale(0, BigDecimal.ROUND_FLOOR);
			int index = 0;
			for (final DetalleOrden det : orden.getDetallesOrden()) {
				try {
					auxPorcentaje = det.getPcIntegracion();
					if (auxPorcentaje.doubleValue() > porcentajeMax
							.doubleValue()) {
						porcentajeMax = auxPorcentaje;
						indexMax = index;
					}
					auxMonto = totalMonto.multiply(auxPorcentaje);
					auxTitulos = auxMonto.divide(precio);
					//auxTitulos = auxTitulos.setScale(0, BigDecimal.ROUND_FLOOR);
					auxTitulos = auxTitulos.setScale(0, BigDecimal.ROUND_HALF_UP);
					auxMonto = auxTitulos.multiply(precio);
					auxPorcentaje = auxMonto.divide(totalMonto,
							MathContext.DECIMAL64);
					sumaTitulos = sumaTitulos.add(auxTitulos);
					det.setCtTituloPost(auxTitulos);
					det.setPcIntegraPost(auxPorcentaje);
					det.setToImportePost(auxMonto);
					det.setPcTasaPost(orden.getPcTasaPost());
					index++;
				} catch (final Exception ex) {
					ex.printStackTrace();
				}
			}
			orden.setToImportePost(totalMonto);
			orden.setCtTituloPost(totalTitulos);
			diferencia = totalTitulos.subtract(sumaTitulos);
			/*
			if (diferencia.intValue() > 0) {
				auxTitulos = orden.getDetallesOrden().get(indexMax)
						.getCtTituloPost();
				auxTitulos = auxTitulos.add(diferencia);
				auxMonto = auxTitulos.multiply(precio);
				auxPorcentaje = auxMonto.divide(totalMonto,
						MathContext.DECIMAL64);
				orden.getDetallesOrden().get(indexMax)
						.setCtTituloPost(auxTitulos);
				orden.getDetallesOrden().get(indexMax)
						.setPcIntegraPost(auxPorcentaje);
				orden.getDetallesOrden().get(indexMax)
						.setToImportePost(auxMonto);
			}
			*/
			validarReparto(orden);
			return orden;
		} catch (final Exception ex) {
			return orden;
		}
	}

	public Orden recalcularPorMonto(final Orden orden) {
		final BigDecimal precio = orden.getImPrecioPost();
		final BigDecimal totalTitulos = orden.getCtTituloPost();
		final BigDecimal totalMonto = orden.getToImportePost();
		BigDecimal auxMonto = BigDecimal.ZERO;
		BigDecimal auxTitulos = BigDecimal.ZERO;
		BigDecimal sumaTitulos = BigDecimal.ZERO;
		int indexMax = -1;
		BigDecimal porcentajeMax = BigDecimal.ZERO;
		BigDecimal auxPorcentaje = BigDecimal.ZERO;
		BigDecimal diferencia = BigDecimal.ZERO;
		int index = 0;
		for (final DetalleOrden det : orden.getDetallesOrden()) {
			try {
				auxPorcentaje = det.getPcIntegraPost();
				if (auxPorcentaje.doubleValue() > porcentajeMax.doubleValue()) {
					porcentajeMax = auxPorcentaje;
					indexMax = index;
				}
				auxMonto = det.getToImportePost();
				auxTitulos = auxMonto.divide(precio, MathContext.DECIMAL64);
				auxTitulos = auxTitulos.setScale(0, BigDecimal.ROUND_FLOOR);
				auxMonto = auxTitulos.multiply(precio);
				auxPorcentaje = auxMonto.divide(totalMonto,
						MathContext.DECIMAL64);
				sumaTitulos = sumaTitulos.add(auxTitulos);
				det.setCtTituloPost(auxTitulos);
				det.setPcIntegraPost(auxPorcentaje);
				det.setToImportePost(auxMonto);
				det.setPcTasaPost(orden.getPcTasaPost());
				index++;
			} catch (final Exception ex) {
				ex.printStackTrace();
			}
		}
		diferencia = totalTitulos.subtract(sumaTitulos);
		if (diferencia.intValue() > 0) {
			auxTitulos = orden.getDetallesOrden().get(indexMax)
					.getCtTituloPost();
			auxTitulos = auxTitulos.add(diferencia);
			auxMonto = auxTitulos.multiply(precio);
			auxPorcentaje = auxMonto.divide(totalMonto, MathContext.DECIMAL64);
			orden.getDetallesOrden().get(indexMax).setCtTituloPost(auxTitulos);
			orden.getDetallesOrden().get(indexMax)
					.setPcIntegraPost(auxPorcentaje);
			orden.getDetallesOrden().get(indexMax).setToImportePost(auxMonto);
		}
		validarReparto(orden);
		return orden;
	}

	public Orden recalcularPorPorcentaje(final Orden orden) {
		final BigDecimal precio = orden.getImPrecioPost();
		final BigDecimal totalTitulos = orden.getCtTituloPost();
		final BigDecimal totalMonto = orden.getToImportePost();
		BigDecimal auxMonto = BigDecimal.ZERO;
		BigDecimal auxTitulos = BigDecimal.ZERO;
		BigDecimal sumaTitulos = BigDecimal.ZERO;
		int indexMax = -1;
		BigDecimal porcentajeMax = BigDecimal.ZERO;
		BigDecimal auxPorcentaje = BigDecimal.ZERO;
		BigDecimal diferencia = BigDecimal.ZERO;
		int index = 0;
		for (final DetalleOrden det : orden.getDetallesOrden()) {
			try {
				auxPorcentaje = det.getPcIntegraPost().divide(
						new BigDecimal(100), MathContext.DECIMAL64);
				if (auxPorcentaje.doubleValue() > porcentajeMax.doubleValue()) {
					porcentajeMax = auxPorcentaje;
					indexMax = index;
				}
				auxMonto = totalMonto.multiply(auxPorcentaje);
				auxTitulos = auxMonto.divide(precio, MathContext.DECIMAL64);
				auxTitulos = auxTitulos.setScale(0, BigDecimal.ROUND_FLOOR);
				auxMonto = auxTitulos.multiply(precio);
				auxPorcentaje = auxMonto.divide(totalMonto,
						MathContext.DECIMAL64);
				sumaTitulos = sumaTitulos.add(auxTitulos);
				det.setCtTituloPost(auxTitulos);
				det.setPcIntegraPost(auxPorcentaje);
				det.setToImportePost(auxMonto);
				det.setPcTasaPost(orden.getPcTasaPost());
				index++;
			} catch (final Exception ex) {
				ex.printStackTrace();
			}
		}
		diferencia = totalTitulos.subtract(sumaTitulos);
		if (diferencia.intValue() > 0) {
			auxTitulos = orden.getDetallesOrden().get(indexMax)
					.getCtTituloPost();
			auxTitulos = auxTitulos.add(diferencia);
			auxMonto = auxTitulos.multiply(precio);
			auxPorcentaje = auxMonto.divide(totalMonto, MathContext.DECIMAL64);
			orden.getDetallesOrden().get(indexMax).setCtTituloPost(auxTitulos);
			orden.getDetallesOrden().get(indexMax)
					.setPcIntegraPost(auxPorcentaje);
			orden.getDetallesOrden().get(indexMax).setToImportePost(auxMonto);
		}
		validarReparto(orden);
		return orden;
	}

	public Orden recalcularPorTitulo(final Orden orden) {
		final BigDecimal precio = orden.getImPrecioPost();
		final BigDecimal totalMonto = orden.getToImportePost();
		BigDecimal auxMonto = BigDecimal.ZERO;
		BigDecimal auxTitulos = BigDecimal.ZERO;
		BigDecimal auxPorcentaje = BigDecimal.ZERO;
		for (final DetalleOrden det : orden.getDetallesOrden()) {
			auxTitulos = det.getCtTituloPost();
			auxMonto = auxTitulos.multiply(precio);
			auxPorcentaje = auxMonto.divide(totalMonto, MathContext.DECIMAL64);
			det.setCtTituloPost(auxTitulos);
			det.setPcIntegraPost(auxPorcentaje);
			det.setToImportePost(auxMonto);
		}
		validarReparto(orden);
		return orden;
	}

	@Override
	public Orden recalcularPostreparto(final Orden orden, final int tipo) {
		switch (tipo) {
		case 1:
			return recalcularPorTitulo(orden);
		case 2:
			return recalcularPorMonto(orden);
		case 3:
			return recalcularPorPorcentaje(orden);
		default:
			break;
		}
		return null;
	}

	public void setServicioOrden(final ServicioOrden servicioOrden) {
		this.servicioOrden = servicioOrden;
	}

	public void setServicioParametro(final ServicioParametro servicioParametro) {
		this.servicioParametro = servicioParametro;
	}

	/**
	 * @param servicioUsuario
	 *            the servicioUsuario to set
	 */
	public void setServicioUsuario(final ServicioUsuario servicioUsuario) {
		this.servicioUsuario = servicioUsuario;
	}

	public String valida(final BigDecimal val) {
		return val != null ? val.toString() : "";
	}

	public String valida(final String val) {
		return StringUtils.isBlank(val) ? "" : val;
	}

	public boolean validarReparto(final Orden orden) {
		BigDecimal sumaTitulos = BigDecimal.ZERO;
		BigDecimal sumaMonto = BigDecimal.ZERO;
		BigDecimal sumaPorc = BigDecimal.ZERO;
		for (final DetalleOrden det : orden.getDetallesOrden()) {
			sumaTitulos = sumaTitulos.add(det.getCtTituloPost());
			sumaMonto = sumaMonto.add(det.getToImportePost());
			sumaPorc = sumaPorc.add(det.getPcIntegraPost());
		}
		if (!sumaTitulos.equals(orden.getCtTituloPost())) {
			return false;
		}
		if (!(sumaMonto.doubleValue() == orden.getToImportePost().doubleValue())) {
			return false;
		}
		return true;
	}
	
	@Override
    public List<BoletaPostReparto> obtenerBoletaPost(final Orden orden) {
          // TODO Auto-generated method stub
          final List<BoletaPostReparto> boletaPostReparto = new ArrayList<BoletaPostReparto>();
          final BoletaPostReparto boletaPost = new BoletaPostReparto();
          boletaPost.setOperacion(orden.getTpOperacion()
                      .equals(new BigDecimal(1)) ? "COMPRA" : "VENTA");
          boletaPost.setFolio(orden.getNuFolio());
          boletaPost.setInstrumento(orden.getInstrumento());
          boletaPost.setFecha(Utilidades.aFechaFormato(new Date(), "dd/MM/yyyy"));
          boletaPost.setToTitulos(orden.getCtTituloPost().toPlainString());          
          boletaPost.setTasa(orden.getPcTasaPost() != null ? orden.getPcTasaPost().toPlainString() :null);
          boletaPost.setPrecio(orden.getImPrecioPost().toPlainString());
          boletaPost.setToOperacion(orden.getToImportePost().toPlainString());
          boletaPostReparto.add(boletaPost);
          for (final DetalleOrden detalle : orden.getDetallesOrden()) {
                final BoletaPostReparto boletaPostDet = new BoletaPostReparto();
                boletaPostDet.setClasificacion(detalle.getNbClasifDelta());
                boletaPostDet.setContrato(detalle.getCdContrato().toString());
                boletaPostDet.setMonto(detalle.getToImportePost().toPlainString());
                boletaPostDet.setPcIntegracion(detalle.getPcIntegraPost().toPlainString());
                boletaPostDet.setTitulos(detalle.getCtTituloPost().toPlainString());
                boletaPostReparto.add(boletaPostDet);
          }
          return boletaPostReparto;
    }

}
